﻿namespace Blaze.Editor
{
    using System;
    using System.Diagnostics;
    using System.Text;
    using EditorOnly;
    using UnityEditor;
    using UnityEditor.SceneManagement;
    using UnityEngine;

    /// <summary>
    /// Blaze编辑器菜单。
    /// </summary>
    [InitializeOnLoad]
    public static class BlazeEditorMenu
    {
        /// <summary>
        /// 定义菜单显示优先级。
        /// </summary>
        public static class Priority
        {
            /// <summary>
            /// 显示在最底部。
            /// </summary>
            public const int Bottom = 1000;

            /// <summary>
            /// 命令。
            /// </summary>
            public const int Commands = 200;

            /// <summary>
            /// 本地测试。
            /// </summary>
            public const int LocalTests = 100;

            /// <summary>
            /// 面板。
            /// </summary>
            public const int Panels = 300;

            /// <summary>
            /// 显示在最顶部。
            /// </summary>
            public const int Top = 0;
        }

        /// <summary>
        /// 当需要同步游戏配置时触发此事件。
        /// </summary>
        public static event Action<SyncConfigsEventArgs> SynchronizingConfigs;

        static BlazeEditorMenu()
        {
            EditorApplication.playModeStateChanged += onEditorPlayModeStageChanged;
        }

        [MenuItem("Blaze/强制重新编译 %#R", false, Priority.Top + 3)]
        public static void ForceRecompile()
        {
            var path = ProjectPath.GetAssets("Blaze/Scripts/EditorOnly/Dummy.cs", true);
            AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate | ImportAssetOptions.ImportRecursive);
        }

        /// <summary>
        /// 快速启动游戏，当游戏停止时自动返回当前编辑的场景。
        /// </summary>
        [MenuItem("Blaze/快速启动游戏 &F5", false, Priority.Top)]
        public static void RapidStartGame()
        {
            if (Application.isPlaying || EditorApplication.isCompiling)
                return;
            if (!EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo())
                return;

            saveCurrentScenePathsToEditorPrefs();

            EditorSceneManager.OpenScene(BlazeEditorConfig.Instance.BootstrapScene, OpenSceneMode.Single);
            EditorApplication.isPlaying = true;
        }

        /// <summary>
        /// 从Configs目录导出配置。
        /// </summary>
        [MenuItem("Blaze/同步游戏配置 &F6", false, Priority.Top + 2)]
        public static void SyncConfigs()
        {
            var args = new SyncConfigsEventArgs();
            if (SynchronizingConfigs != null)
                SynchronizingConfigs(args);

            var exe = BlazeEditorConfig.Instance.ConfigExportTool + ".exe";
            var process = new Process
            {
                StartInfo =
                {
                    FileName = ProjectPath.Get("Tools/bin/" + exe),
                    Arguments = args.Arguments,
                    WorkingDirectory = ProjectPath.Get("Tools/bin"),
                }
            };
            var success = process.Start();
            if (!success)
                throw new Exception(string.Format("run {0} failed.", exe));
            process.WaitForExit();
        }

        private static void onEditorPlayModeStageChanged(PlayModeStateChange state)
        {
            if (EditorApplication.isPlayingOrWillChangePlaymode)
                return;
            if (EditorApplication.isPlaying)
                return;

            var savedData = ProjectEditorPrefs.GetString(mOpenScenesOnStopPlaying);
            if (string.IsNullOrEmpty(savedData))
                return;

            var scenePathArray = savedData.Split(";".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
            for (var i = 0; i < scenePathArray.Length; i++)
            {
                if (i == 0)
                    EditorSceneManager.OpenScene(scenePathArray[0], OpenSceneMode.Single);
                else
                    EditorSceneManager.OpenScene(scenePathArray[i], OpenSceneMode.Additive);
            }
            ProjectEditorPrefs.SetString(mOpenScenesOnStopPlaying, string.Empty);
        }

        private static void saveCurrentScenePathsToEditorPrefs()
        {
            var buffer = new StringBuilder();
            for (var i = 0; i < EditorSceneManager.loadedSceneCount; i++)
            {
                var scene = EditorSceneManager.GetSceneAt(i);
                buffer.AppendFormat("{0};", scene.path);
            }
            ProjectEditorPrefs.SetString(mOpenScenesOnStopPlaying, buffer.ToString());
        }

        private const string mOpenScenesOnStopPlaying = "OpenScenePathsOnStopPlaying";
    }
}